﻿#include "GUISEASubSysBeamDialog.h"
#include "ui_GUISEASubSysBeamDialog.h"

#include "FITK_Kernel/FITKCore/FITKActionOperator.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITK_Kernel/FITKCore/FITKActionOperator.h"

#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsSEAModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscNodeList.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEASubSysBeam.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEASubSysGeoProp.h"

#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsPhysics.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbsPhysicsProp.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsSpectraManager.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbstractSpectra.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKPhyscisPropertyBeam.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbsMaterial.h"

#include "PickDataProvider/PickedDataProvider.h"
#include "PickDataProvider/PickedData.h"

#include <QMessageBox>
#include <QStandardItemModel>

namespace GUI {

    GUISEASubSysBeamDialog::GUISEASubSysBeamDialog(Acoustics::FITKSEASubSysBeam* obj, Core::FITKActionOperator* oper, QWidget* parent /*= nullptr*/) :
        GUISEASubSysBaseDialog(obj, oper, parent),
        _ui(new Ui::GUISEASubSysBeamDialog)
    {
        _ui->setupUi(this);
        //连接信号关联触发动作
        connect(_ui->checkBox_Flexure_XModalDen, &QCheckBox::stateChanged, this, [this](int state) {
            if (state == Qt::Checked) { _ui->comboBox_Flexure_XModal->setEnabled(true); }
            else if (state == Qt::Unchecked) { _ui->comboBox_Flexure_XModal->setEnabled(false); }});
        connect(_ui->checkBox_Flexure_YModalDen, &QCheckBox::stateChanged, this, [this](int state) {
            if (state == Qt::Checked) { _ui->comboBox_Flexure_YModal->setEnabled(true); }
            else if (state == Qt::Unchecked) { _ui->comboBox_Flexure_YModal->setEnabled(false); }});
        connect(_ui->checkBox_ExtensionModalDen, &QCheckBox::stateChanged, this, [this](int state) {
            if (state == Qt::Checked) { _ui->comboBox_ExtensionModal->setEnabled(true); }
            else if (state == Qt::Unchecked) { _ui->comboBox_ExtensionModal->setEnabled(false); }});
        connect(_ui->checkBox_TorsionModelDen, &QCheckBox::stateChanged, this, [this](int state) {
            if (state == Qt::Checked) { _ui->comboBox_TorsionModel->setEnabled(true); }
            else if (state == Qt::Unchecked) { _ui->comboBox_TorsionModel->setEnabled(false); }});
        //初始化界面
        _ui->label_image->setPixmap(QPixmap(":/icons/Beam.png"));
        _ui->label_GeoImage->setPixmap(QPixmap(":/icons/Beam2.png"));
        _tableView_modelBeamNodes = new QStandardItemModel();
        _ui->tableView_BoundaryNodes->setModel(_tableView_modelBeamNodes);
        _tableView_modelOrientationNode = new QStandardItemModel();
        _ui->tableView_OrientationNode->setModel(_tableView_modelOrientationNode);
        //初始化数据
        this->initData();
    }

    GUISEASubSysBeamDialog::~GUISEASubSysBeamDialog()
    {
        //释放数据
        if (_ui) {
            delete _ui;
            _ui = nullptr;
        }
        if (_tableView_modelBeamNodes) {
            delete _tableView_modelBeamNodes;
            _tableView_modelBeamNodes = nullptr;
        }
        if (_tableView_modelOrientationNode) {
            delete _tableView_modelOrientationNode;
            _tableView_modelOrientationNode = nullptr;
        }
    }

    void GUISEASubSysBeamDialog::initData()
    {
        //获取板数据信息
        QString name;
        if (_obj)
        {
            //获取名称
            name = _obj->getDataObjectName();
            if (name.isEmpty())
                name = this->ckeckNameFromMgr("Beam");
        }
        //初始化数据名称
        _ui->lineEdit_Name->setText(name);
        //初始化参数
        this->initPhysicalPropData();
        this->initDampingData();
        this->initModelDensityData();
        this->initGeometryData();
        QString operModel;
        if (!_isCreate)
        {
            this->initUserData();
        }
        this->initPropData();
    }

    void GUISEASubSysBeamDialog::on_pushButton_Cancel_clicked()
    {
        this->reject();
    }

    void GUISEASubSysBeamDialog::on_pushButton_OK_clicked()
    {
        if (!_oper)return;
    //保存执行的脚本
        _pyStr.append("seaSubSys=SEA.SEABeam()");
    //获取操作器动作类型
        if (_isCreate)
        {
            Acoustics::FITKSEASubSysBeam* beam = dynamic_cast<Acoustics::FITKSEASubSysBeam*>(_obj);
            if (!beam)return;
            auto nodes = beam->getNodes();
            for (Acoustics::FITKAbstractSEASubSysWithNodes::SubSysNode node : nodes)
            {
                _pyStr.append(QString("seaSubSys.addPoint(%1)").arg(node._id));
            }
            _pyStr.append("seaSubSys.createBeam()");
            if (!this->createObjData())
                return;
        }
        else
        {
            _pyStr.append(QString("seaSubSys=SEA.SEABeam.GetSEABeam('%1')").arg(_obj->getDataObjectName()));
            if (!this->editObjData())
                return;
        }
        this->saveScript(_pyStr);
        this->accept();
    }

    void GUISEASubSysBeamDialog::on_comboBox_PhysicalProp_currentIndexChanged(int index)
    {
        this->initPropData();
    }

    void GUISEASubSysBeamDialog::initPhysicalPropData()
    {
        //清空数据下拉链表
        _ui->comboBox_PhysicalProp->clear();
        //初始化物理属性下拉列表
        Acoustics::FITKAcousticsPhysics* phyMgr = FITKAPP->getGlobalData()->getPhysicsData<Acoustics::FITKAcousticsPhysics>();
        if (!phyMgr)return;
        //获取物理属性管理器
        Acoustics::FITKAcousticsPhysicsPropManager* phyPropMgr = phyMgr->getPhysicsPropManager();
        if (!phyPropMgr)return;
        QList<Acoustics::FITKAcousticsAbsPhysicsProp*> propDataList = phyPropMgr->getPhysicsProps(Acoustics::FITKAcousticsAbsPhysicsProp::AcousticsPhyscisPropType::APPBeam);
        for (QList<Acoustics::FITKAcousticsAbsPhysicsProp*>::iterator iter = propDataList.begin(); iter != propDataList.end(); ++iter)
        {
            if (*iter == nullptr)continue;
            _ui->comboBox_PhysicalProp->addItem((*iter)->getDataObjectName(), (*iter)->getDataObjectID());
        }
    }

    void GUISEASubSysBeamDialog::initDampingData()
    {
        //清空数据下拉链表
        _ui->comboBox_Flexure_X->clear();
        _ui->comboBox_Flexure_Y->clear();
        _ui->comboBox_Extension_Z->clear();
        _ui->comboBox_Torsion_ZZ->clear();
        //初始化损耗因子下拉列表
        Acoustics::FITKAcousticsPhysics* phyMgr = FITKAPP->getGlobalData()->getPhysicsData<Acoustics::FITKAcousticsPhysics>();
        if (!phyMgr)return;
        //获取频谱管理器
        Acoustics::FITKAcousticsSpectraManager* spectraMgr = phyMgr->getFITKAcousticsSpectraManager();
        if (!spectraMgr)return;
        QList<Acoustics::FITKAcousticsAbstractSpectra*> spectraList = spectraMgr->getSpectraByType(Acoustics::FITKAcousticsAbstractSpectra::AcousticsSpectraType::Damping);
        for (QList<Acoustics::FITKAcousticsAbstractSpectra*>::iterator iter = spectraList.begin(); iter != spectraList.end(); ++iter)
        {
            if (*iter == nullptr)continue;
            _ui->comboBox_Flexure_X->addItem((*iter)->getDataObjectName(), (*iter)->getDataObjectID());
            _ui->comboBox_Flexure_Y->addItem((*iter)->getDataObjectName(), (*iter)->getDataObjectID());
            _ui->comboBox_Extension_Z->addItem((*iter)->getDataObjectName(), (*iter)->getDataObjectID());
            _ui->comboBox_Torsion_ZZ->addItem((*iter)->getDataObjectName(), (*iter)->getDataObjectID());
        }
    }

    void GUISEASubSysBeamDialog::initModelDensityData()
    {
        //初始化模态密度的下拉列表
        Acoustics::FITKAcousticsPhysics* phyMgr = FITKAPP->getGlobalData()->getPhysicsData<Acoustics::FITKAcousticsPhysics>();
        if (!phyMgr)return;
        //获取频谱管理器
        Acoustics::FITKAcousticsSpectraManager* spectraManager = phyMgr->getFITKAcousticsSpectraManager();
        if (!spectraManager)return;
        QList<Acoustics::FITKAcousticsAbstractSpectra*> spectraList = spectraManager->getSpectraByType(Acoustics::FITKAcousticsAbstractSpectra::AcousticsSpectraType::ModalDensity);
        for (QList<Acoustics::FITKAcousticsAbstractSpectra*>::iterator iter = spectraList.begin(); iter != spectraList.end(); ++iter)
        {
            if (*iter == nullptr)continue;
            _ui->comboBox_Flexure_XModal->addItem((*iter)->getDataObjectName(), (*iter)->getDataObjectID());
            _ui->comboBox_Flexure_YModal->addItem((*iter)->getDataObjectName(), (*iter)->getDataObjectID());
            _ui->comboBox_ExtensionModal->addItem((*iter)->getDataObjectName(), (*iter)->getDataObjectID());
            _ui->comboBox_TorsionModel->addItem((*iter)->getDataObjectName(), (*iter)->getDataObjectID());
        }
    }

    void GUISEASubSysBeamDialog::initPropData()
    {
        int propID = _ui->comboBox_PhysicalProp->currentData().toInt();
        //获取板的几何属性
        Acoustics::FITKSEASubSysGeoProp* geoProp = _obj->getGeoProp();
        if (!geoProp)return;
        //获取长度
        double length = geoProp->getGeoProp(Acoustics::FITKSEASubSysGeoProp::GeoPropType::Circumference);
        //初始化物理属性下拉列表
        Acoustics::FITKAcousticsPhysics* phyMgr = FITKAPP->getGlobalData()->getPhysicsData<Acoustics::FITKAcousticsPhysics>();
        if (!phyMgr) return;
        //获取物理属性管理器
        Acoustics::FITKAcousticsPhysicsPropManager* phyPropMgr = phyMgr->getPhysicsPropManager();
        if (!phyPropMgr) return;
        Acoustics::FITKPhyscisPropertyBeam* beamPhyPropData = dynamic_cast<Acoustics::FITKPhyscisPropertyBeam*>(phyPropMgr->getDataByID(propID));
        if (!beamPhyPropData) return;
        Acoustics::FITKAcousticsAbsMaterial* materialData = beamPhyPropData->getMaterial();
        if (!materialData)return;
        //计算获取面积和质量
        double area = beamPhyPropData->getCrossSectionArea() * length;
        double mass = area * materialData->getDensity();
        //设置参数到界面
        _ui->lineEdit_PhyProp->setText(beamPhyPropData->getDataObjectName());
        _ui->lineEdit_Material->setText(materialData->getDataObjectName());
        _ui->lineEdit_Mass->setText(QString::number(mass));
        _ui->lineEdit_Length->setText(QString::number(length));
        _ui->lineEdit_Area->setText(QString::number(area));
        _ui->lineEdit_Perimeter->setText(QString::number(beamPhyPropData->getPerimeter()));
        _ui->lineEdit_lxx->setText(QString::number(beamPhyPropData->getSecondMomentX()));
        _ui->lineEdit_lyy->setText(QString::number(beamPhyPropData->getSecondMomentY()));
        _ui->lineEdit_Jzz->setText(QString::number(beamPhyPropData->getPolarMoment()));
        _ui->lineEdit_Qzz->setText(QString::number(beamPhyPropData->getTorsionalConstant()));
    }

    void GUISEASubSysBeamDialog::initGeometryData()
    {
        int propID = _ui->comboBox_PhysicalProp->currentData().toInt();
        //获取板的几何属性
        Acoustics::FITKSEASubSysGeoProp* geoProp = _obj->getGeoProp();
        if (!geoProp)return;
        //获取长度
        double length = geoProp->getGeoProp(Acoustics::FITKSEASubSysGeoProp::GeoPropType::Circumference);
        //初始化物理属性下拉列表
        Acoustics::FITKAcousticsPhysics* phyMgr = FITKAPP->getGlobalData()->getPhysicsData<Acoustics::FITKAcousticsPhysics>();
        if (!phyMgr) return;
        //获取物理属性管理器
        Acoustics::FITKAcousticsPhysicsPropManager* phyPropMgr = phyMgr->getPhysicsPropManager();
        if (!phyPropMgr) return;
        Acoustics::FITKPhyscisPropertyBeam* beamPhyPropData = dynamic_cast<Acoustics::FITKPhyscisPropertyBeam*>(phyPropMgr->getDataByID(propID));
        if (!beamPhyPropData) return;
        double surfaceArea = length * beamPhyPropData->getPerimeter();
        _ui->lineEdit_LengthDim->setText(QString::number(length));
        _ui->lineEdit_AreaDim->setText(QString::number(surfaceArea));
        //获取离散数据
        Acoustics::FITKAcousticsDiscModel* discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (!discModel)return;
        //获取节点管理器
        Acoustics::FITKAcousticsDiscNodeList* seaNodesList = discModel->getNodes();
        if (!seaNodesList)return;

        //获取节点数据
        QList<int> nodesIDList = _obj->getNodeIDs();
        QStringList tableView_headers;
        tableView_headers << tr("ID") << tr("X") << tr("Y") << tr("Z");
        //设置梁的节点
        _tableView_modelBeamNodes->clear();
        _tableView_modelBeamNodes->setHorizontalHeaderLabels(tableView_headers);
        for (int i = 0; i < nodesIDList.size() - 1; ++i)
        {
            int id = nodesIDList.at(i);
            Core::FITKNode* nodeData = seaNodesList->getNodeByID(id);
            if (!nodeData)continue;
            _tableView_modelBeamNodes->setItem(i, 0, new QStandardItem(QString::number(id)));
            _tableView_modelBeamNodes->setItem(i, 1, new QStandardItem(QString::number(nodeData->x())));
            _tableView_modelBeamNodes->setItem(i, 2, new QStandardItem(QString::number(nodeData->y())));
            _tableView_modelBeamNodes->setItem(i, 3, new QStandardItem(QString::number(nodeData->z())));
        }
        // 表格宽度自动根据UI进行计算，不可手动调整宽度
        _ui->tableView_BoundaryNodes->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
        _ui->tableView_BoundaryNodes->setEditTriggers(QAbstractItemView::NoEditTriggers);

        //设置方向点
        _tableView_modelOrientationNode->clear();
        _tableView_modelOrientationNode->setHorizontalHeaderLabels(tableView_headers);
        int lasetNodeID = nodesIDList.last();
        Core::FITKNode* nodeData = seaNodesList->getNodeByID(lasetNodeID);
        if (!nodeData)return;
        _tableView_modelOrientationNode->setItem(0, 0, new QStandardItem(QString::number(lasetNodeID)));
        _tableView_modelOrientationNode->setItem(0, 1, new QStandardItem(QString::number(nodeData->x())));
        _tableView_modelOrientationNode->setItem(0, 2, new QStandardItem(QString::number(nodeData->y())));
        _tableView_modelOrientationNode->setItem(0, 3, new QStandardItem(QString::number(nodeData->z())));
        // 表格宽度自动根据UI进行计算，不可手动调整宽度
        _ui->tableView_OrientationNode->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
        _ui->tableView_OrientationNode->setEditTriggers(QAbstractItemView::NoEditTriggers);
    }

    void GUISEASubSysBeamDialog::initUserData()
    {
        Acoustics::FITKSEASubSysBeam* beamData = dynamic_cast<Acoustics::FITKSEASubSysBeam*>(_obj);
        if (!beamData) return;
    //General板块用户设置数据初始化
        int proID = _obj->getPropSectionID();
        int index = _ui->comboBox_PhysicalProp->findData(proID);
        _ui->comboBox_PhysicalProp->setCurrentIndex(index);
        int flexureXID = beamData->getFlexureXSpectraID();
        int index1 = _ui->comboBox_Flexure_X->findData(flexureXID);
        _ui->comboBox_Flexure_X->setCurrentIndex(index1);
        int flexureYID = beamData->getFlexureYSpectraID();
        int index2 = _ui->comboBox_Flexure_Y->findData(flexureYID);
        _ui->comboBox_Flexure_Y->setCurrentIndex(index2);
        int extensionZID = beamData->getExtensionZSpectraID();
        int index3 = _ui->comboBox_Extension_Z->findData(extensionZID);
        _ui->comboBox_Extension_Z->setCurrentIndex(index3);
        int torsionZZID = beamData->getTorsionZZSpectraID();
        int index4 = _ui->comboBox_Torsion_ZZ->findData(torsionZZID);
        _ui->comboBox_Torsion_ZZ->setCurrentIndex(index4);
    //Wave板块用户设置数据初始化
        _ui->checkBox_EnableFlexure_X->setChecked(beamData->getFlexureXInSEAMatrixSolution());
        _ui->checkBox_EnableFlexure_Y->setChecked(beamData->getFlexureYInSEAMatrixSolution());
        _ui->checkBox_EnableExtension->setChecked(beamData->getExtensionZInSEAMatrixSolution());
        _ui->checkBox_EnableTorsion->setChecked(beamData->getTorsionZZInSEAMatrixSolution());
        bool flexureX = beamData->getFlexureXModelDensityState();
        bool flexureY = beamData->getFlexureYModelDensityState();
        bool extension = beamData->getExtensionZModelDensityState();
        bool torsion = beamData->getTorsionZZModelDensityState();
        if (flexureX) {
            _ui->checkBox_Flexure_XModalDen->setChecked(flexureX);
            int ID = beamData->getFlexureXModelDensityID();
            int index = _ui->comboBox_Flexure_XModal->findData(ID);
            _ui->comboBox_Flexure_XModal->setCurrentIndex(index );
        }
        if (flexureY) {
            _ui->checkBox_Flexure_YModalDen->setChecked(flexureY);
            int ID = beamData->getFlexureYModelDensityID();
            int index = _ui->comboBox_Flexure_YModal->findData(ID);
            _ui->comboBox_Flexure_YModal->setCurrentIndex(index);
        }
        if (extension) {
            _ui->checkBox_ExtensionModalDen->setChecked(extension);
            int ID = beamData->getExtensionZModelDensityID();
            int index = _ui->comboBox_ExtensionModal->findData(ID);
            _ui->comboBox_ExtensionModal->setCurrentIndex(index );
        }
        if (torsion) {
            _ui->checkBox_TorsionModelDen->setChecked(torsion);
            int ID = beamData->getTorsionZZModelDensityID();
            int index = _ui->comboBox_TorsionModel->findData(ID);
            _ui->comboBox_TorsionModel->setCurrentIndex(index );
        }
    }

    void GUISEASubSysBeamDialog::getDataFormWidget()
    {
        Acoustics::FITKSEASubSysBeam* beamData = dynamic_cast<Acoustics::FITKSEASubSysBeam*>(_obj);
        if (!beamData) return;

    //General板块数据存储
        _pyStr.append(QString("seaSubSys.setPhysicalProp('%1')").arg(_ui->comboBox_PhysicalProp->currentText()));
        beamData->setPropSection(_ui->comboBox_PhysicalProp->currentData().toInt());

        int flexureXID = _ui->comboBox_Flexure_X->currentData().toInt();
        int flexureYID = _ui->comboBox_Flexure_Y->currentData().toInt();
        int extensionZID = _ui->comboBox_Extension_Z->currentData().toInt();
        int torsionZZID = _ui->comboBox_Torsion_ZZ->currentData().toInt();

        _pyStr.append(QString("seaSubSys.setDamping(1,'%1')").arg(_ui->comboBox_Flexure_X->currentText()));
        _pyStr.append(QString("seaSubSys.setDamping(2,'%1')").arg(_ui->comboBox_Flexure_Y->currentText()));
        _pyStr.append(QString("seaSubSys.setDamping(3,'%1')").arg(_ui->comboBox_Extension_Z->currentText()));
        _pyStr.append(QString("seaSubSys.setDamping(4,'%1')").arg(_ui->comboBox_Torsion_ZZ->currentText()));

        beamData->setFlexureXSpectraID(flexureXID);
        beamData->setFlexureYSpectraID(flexureYID);
        beamData->setExtensionZSpectraID(extensionZID);
        beamData->setTorsionZZSpectraID(torsionZZID);

    //Wave板块数据存储
        bool SEAflexureX = _ui->checkBox_EnableFlexure_X->isChecked();
        bool SEAflexureY = _ui->checkBox_EnableFlexure_Y->isChecked();
        bool SEAextension = _ui->checkBox_EnableExtension->isChecked();
        bool SEAtorsion = _ui->checkBox_EnableTorsion->isChecked();

        beamData->setFlexureXInSEAMatrixSolution(SEAflexureX);
        beamData->setFlexureYInSEAMatrixSolution(SEAflexureY);
        beamData->setExtensionZInSEAMatrixSolution(SEAextension);
        beamData->setTorsionZZInSEAMatrixSolution(SEAtorsion);

        bool flexureX = _ui->checkBox_Flexure_XModalDen->isChecked();
        bool flexureY = _ui->checkBox_Flexure_YModalDen->isChecked();
        bool extension = _ui->checkBox_ExtensionModalDen->isChecked();
        bool torsion = _ui->checkBox_TorsionModelDen->isChecked();

        beamData->setFlexureXModelDensityState(flexureX);
        beamData->setFlexureYModelDensityState(flexureY);
        beamData->setExtensionZModelDensityState(extension);
        beamData->setTorsionZZModelDensityState(torsion);

        if (flexureX) 
            beamData->setFlexureXModelDensityID(_ui->comboBox_Flexure_XModal->currentData().toInt());
        if (flexureY) 
            beamData->setFlexureYModelDensityID(_ui->comboBox_Flexure_YModal->currentData().toInt());
        if (extension) 
            beamData->setExtensionZModelDensityID(_ui->comboBox_ExtensionModal->currentData().toInt());
        if (torsion) 
            beamData->setTorsionZZModelDensityID(_ui->comboBox_TorsionModel->currentData().toInt());

        _pyStr.append(QString("seaSubSys.setSEAMatrixSolution_ModalDensity(1,%1,%2,'%3')").arg(SEAflexureX).arg(flexureX).arg(_ui->comboBox_Flexure_XModal->currentText()));
        _pyStr.append(QString("seaSubSys.setSEAMatrixSolution_ModalDensity(2,%1,%2,'%3')").arg(SEAflexureY).arg(flexureY).arg(_ui->comboBox_Flexure_YModal->currentText()));
        _pyStr.append(QString("seaSubSys.setSEAMatrixSolution_ModalDensity(3,%1,%2,'%3')").arg(SEAextension).arg(extension).arg(_ui->comboBox_ExtensionModal->currentText()));
        _pyStr.append(QString("seaSubSys.setSEAMatrixSolution_ModalDensity(4,%1,%2,'%3')").arg(SEAtorsion).arg(torsion).arg(_ui->comboBox_TorsionModel->currentText()));
    }

    QString GUISEASubSysBeamDialog::getNameFormWidget()
    {
        return _ui->lineEdit_Name->text();
    }
}
